{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 时区处理\n",
    "\n",
    "本教程介绍Pandas中的时区处理，包括时区转换、本地化、UTC处理等操作。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "from datetime import datetime\n",
    "import pytz"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. 时区基础概念"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建无时区信息的时间序列\n",
    "naive_ts = pd.Timestamp('2023-06-15 14:30:00')\n",
    "print(f\"无时区时间戳: {naive_ts}\")\n",
    "print(f\"时区信息: {naive_ts.tz}\")\n",
    "print(f\"是否有时区: {naive_ts.tz is not None}\")\n",
    "\n",
    "# 查看可用时区\n",
    "print(f\"\\n常用时区示例:\")\n",
    "common_timezones = [\n",
    "    'UTC',\n",
    "    'US/Eastern',\n",
    "    'US/Pacific', \n",
    "    'Europe/London',\n",
    "    'Asia/Shanghai',\n",
    "    'Asia/Tokyo',\n",
    "    'Australia/Sydney'\n",
    "]\n",
    "\n",
    "for tz in common_timezones:\n",
    "    print(f\"  {tz}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. 时区本地化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 为无时区的时间戳添加时区信息\n",
    "naive_ts = pd.Timestamp('2023-06-15 14:30:00')\n",
    "\n",
    "# 本地化为不同时区\n",
    "utc_ts = naive_ts.tz_localize('UTC')\n",
    "shanghai_ts = naive_ts.tz_localize('Asia/Shanghai')\n",
    "ny_ts = naive_ts.tz_localize('US/Eastern')\n",
    "\n",
    "print(\"时区本地化结果:\")\n",
    "print(f\"原始（无时区）: {naive_ts}\")\n",
    "print(f\"UTC时区:        {utc_ts}\")\n",
    "print(f\"上海时区:       {shanghai_ts}\")\n",
    "print(f\"纽约时区:       {ny_ts}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 对时间序列进行时区本地化\n",
    "dates = pd.date_range('2023-06-15', periods=5, freq='D')\n",
    "ts_series = pd.Series(range(5), index=dates)\n",
    "\n",
    "print(\"原始时间序列:\")\n",
    "print(ts_series)\n",
    "print(f\"时区信息: {ts_series.index.tz}\")\n",
    "\n",
    "# 本地化为UTC\n",
    "utc_series = ts_series.tz_localize('UTC')\n",
    "print(\"\\nUTC本地化后:\")\n",
    "print(utc_series)\n",
    "print(f\"时区信息: {utc_series.index.tz}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. 时区转换"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建UTC时间序列\n",
    "utc_dates = pd.date_range('2023-06-15 12:00:00', periods=6, freq='4H', tz='UTC')\n",
    "utc_series = pd.Series(range(6), index=utc_dates)\n",
    "\n",
    "print(\"UTC时间序列:\")\n",
    "print(utc_series)\n",
    "\n",
    "# 转换到不同时区\n",
    "timezones = {\n",
    "    'Asia/Shanghai': '上海',\n",
    "    'Asia/Tokyo': '东京',\n",
    "    'Europe/London': '伦敦',\n",
    "    'US/Eastern': '纽约',\n",
    "    'US/Pacific': '洛杉矶'\n",
    "}\n",
    "\n",
    "print(\"\\n转换到不同时区:\")\n",
    "for tz, name in timezones.items():\n",
    "    converted = utc_series.tz_convert(tz)\n",
    "    print(f\"{name:6} ({tz:15}): {converted.index[0]}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 时区转换对比\n",
    "utc_time = pd.Timestamp('2023-06-15 12:00:00', tz='UTC')\n",
    "\n",
    "timezone_comparison = pd.DataFrame({\n",
    "    'timezone': list(timezones.keys()),\n",
    "    'city': list(timezones.values()),\n",
    "    'local_time': [utc_time.tz_convert(tz) for tz in timezones.keys()],\n",
    "    'utc_offset': [utc_time.tz_convert(tz).strftime('%z') for tz in timezones.keys()]\n",
    "})\n",
    "\n",
    "print(\"时区转换对比表:\")\n",
    "print(timezone_comparison)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. 夏令时处理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建跨越夏令时转换的时间序列\n",
    "# 美国东部时间的夏令时转换通常在3月和11月\n",
    "dst_dates = pd.date_range('2023-03-11', '2023-03-13', freq='6H', tz='US/Eastern')\n",
    "dst_series = pd.Series(range(len(dst_dates)), index=dst_dates)\n",
    "\n",
    "print(\"夏令时转换期间的时间序列（美国东部时间）:\")\n",
    "print(dst_series)\n",
    "\n",
    "# 转换为UTC查看实际时间间隔\n",
    "utc_converted = dst_series.tz_convert('UTC')\n",
    "print(\"\\n转换为UTC:\")\n",
    "print(utc_converted)\n",
    "\n",
    "# 查看时间间隔\n",
    "time_diffs = utc_converted.index.to_series().diff()\n",
    "print(\"\\n时间间隔:\")\n",
    "print(time_diffs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 处理模糊时间（夏令时结束时重复的小时）\n",
    "# 创建夏令时结束时的时间\n",
    "ambiguous_time = '2023-11-05 01:30:00'\n",
    "\n",
    "print(\"处理夏令时结束时的模糊时间:\")\n",
    "try:\n",
    "    # 这可能会引发错误，因为时间是模糊的\n",
    "    ambiguous_ts = pd.Timestamp(ambiguous_time, tz='US/Eastern')\n",
    "    print(f\"模糊时间: {ambiguous_ts}\")\n",
    "except Exception as e:\n",
    "    print(f\"错误: {e}\")\n",
    "\n",
    "# 明确指定是夏令时还是标准时\n",
    "try:\n",
    "    # 使用pytz明确处理\n",
    "    eastern = pytz.timezone('US/Eastern')\n",
    "    dt_naive = datetime(2023, 11, 5, 1, 30, 0)\n",
    "    \n",
    "    # 夏令时版本\n",
    "    dt_dst = eastern.localize(dt_naive, is_dst=True)\n",
    "    print(f\"夏令时版本: {dt_dst}\")\n",
    "    \n",
    "    # 标准时版本\n",
    "    dt_std = eastern.localize(dt_naive, is_dst=False)\n",
    "    print(f\"标准时版本: {dt_std}\")\n",
    "    \n",
    "except Exception as e:\n",
    "    print(f\"处理模糊时间时出错: {e}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5. 时区感知的数据操作"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建不同时区的时间序列\n",
    "utc_ts = pd.Series(\n",
    "    range(5), \n",
    "    index=pd.date_range('2023-06-15 12:00', periods=5, freq='H', tz='UTC')\n",
    ")\n",
    "\n",
    "shanghai_ts = pd.Series(\n",
    "    range(10, 15), \n",
    "    index=pd.date_range('2023-06-15 20:00', periods=5, freq='H', tz='Asia/Shanghai')\n",
    ")\n",
    "\n",
    "print(\"UTC时间序列:\")\n",
    "print(utc_ts)\n",
    "print(\"\\n上海时间序列:\")\n",
    "print(shanghai_ts)\n",
    "\n",
    "# 合并不同时区的数据\n",
    "combined = pd.concat([utc_ts, shanghai_ts], keys=['UTC', 'Shanghai'])\n",
    "print(\"\\n合并后的数据:\")\n",
    "print(combined)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 时区对齐操作\n",
    "# 将所有数据转换为同一时区进行比较\n",
    "utc_aligned = utc_ts\n",
    "shanghai_aligned = shanghai_ts.tz_convert('UTC')\n",
    "\n",
    "print(\"时区对齐后的数据:\")\n",
    "print(\"UTC (原始):\")\n",
    "print(utc_aligned)\n",
    "print(\"\\n上海转UTC:\")\n",
    "print(shanghai_aligned)\n",
    "\n",
    "# 创建对齐的DataFrame\n",
    "aligned_df = pd.DataFrame({\n",
    "    'utc_data': utc_aligned,\n",
    "    'shanghai_data': shanghai_aligned\n",
    "})\n",
    "\n",
    "print(\"\\n对齐的DataFrame:\")\n",
    "print(aligned_df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6. 实际应用示例"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 模拟全球股票交易数据\n",
    "np.random.seed(42)\n",
    "\n",
    "# 不同市场的交易时间\n",
    "markets = {\n",
    "    'Shanghai': {\n",
    "        'timezone': 'Asia/Shanghai',\n",
    "        'trading_hours': ('09:30', '15:00')\n",
    "    },\n",
    "    'Tokyo': {\n",
    "        'timezone': 'Asia/Tokyo', \n",
    "        'trading_hours': ('09:00', '15:00')\n",
    "    },\n",
    "    'London': {\n",
    "        'timezone': 'Europe/London',\n",
    "        'trading_hours': ('08:00', '16:30')\n",
    "    },\n",
    "    'New_York': {\n",
    "        'timezone': 'US/Eastern',\n",
    "        'trading_hours': ('09:30', '16:00')\n",
    "    }\n",
    "}\n",
    "\n",
    "# 创建各市场的交易数据\n",
    "trading_data = {}\n",
    "base_date = '2023-06-15'\n",
    "\n",
    "for market, info in markets.items():\n",
    "    # 创建交易时间\n",
    "    start_time = f\"{base_date} {info['trading_hours'][0]}\"\n",
    "    trading_dates = pd.date_range(\n",
    "        start_time, \n",
    "        periods=20, \n",
    "        freq='30min', \n",
    "        tz=info['timezone']\n",
    "    )\n",
    "    \n",
    "    # 模拟价格数据\n",
    "    prices = 100 + np.cumsum(np.random.randn(20) * 0.5)\n",
    "    \n",
    "    trading_data[market] = pd.Series(prices, index=trading_dates)\n",
    "\n",
    "print(\"各市场交易数据（前5个时间点）:\")\n",
    "for market, data in trading_data.items():\n",
    "    print(f\"\\n{market}:\")\n",
    "    print(data.head())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 将所有市场数据转换为UTC进行统一分析\n",
    "utc_trading_data = {}\n",
    "for market, data in trading_data.items():\n",
    "    utc_trading_data[market] = data.tz_convert('UTC')\n",
    "\n",
    "# 合并所有市场数据\n",
    "all_markets_df = pd.DataFrame(utc_trading_data)\n",
    "\n",
    "print(\"UTC时区下的全球市场数据（前10行）:\")\n",
    "print(all_markets_df.head(10))\n",
    "\n",
    "# 计算各市场的相关性\n",
    "correlation_matrix = all_markets_df.corr()\n",
    "print(\"\\n市场间相关性:\")\n",
    "print(correlation_matrix.round(3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 分析全球交易活跃时间\n",
    "# 统计每个UTC小时的交易活跃度\n",
    "all_data_combined = pd.concat(utc_trading_data.values())\n",
    "hourly_activity = all_data_combined.groupby(all_data_combined.index.hour).count()\n",
    "\n",
    "print(\"各UTC小时的交易活跃度:\")\n",
    "activity_df = pd.DataFrame({\n",
    "    'utc_hour': hourly_activity.index,\n",
    "    'activity_count': hourly_activity.values\n",
    "})\n",
    "\n",
    "# 添加对应的各时区时间\n",
    "sample_utc_time = pd.Timestamp('2023-06-15 12:00:00', tz='UTC')\n",
    "for hour in range(24):\n",
    "    utc_time = sample_utc_time.replace(hour=hour)\n",
    "    if hour < len(activity_df):\n",
    "        print(f\"UTC {hour:2d}:00 - 活跃度: {hourly_activity.get(hour, 0):2d} - \"\n",
    "              f\"上海: {utc_time.tz_convert('Asia/Shanghai').strftime('%H:%M')}, \"\n",
    "              f\"伦敦: {utc_time.tz_convert('Europe/London').strftime('%H:%M')}, \"\n",
    "              f\"纽约: {utc_time.tz_convert('US/Eastern').strftime('%H:%M')}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 时区转换工具函数\n",
    "def convert_timezone_batch(timestamps, from_tz, to_tz):\n",
    "    \"\"\"\n",
    "    批量时区转换函数\n",
    "    \"\"\"\n",
    "    if isinstance(timestamps, (list, tuple)):\n",
    "        timestamps = pd.Series(pd.to_datetime(timestamps))\n",
    "    \n",
    "    # 本地化\n",
    "    if timestamps.dt.tz is None:\n",
    "        localized = timestamps.dt.tz_localize(from_tz)\n",
    "    else:\n",
    "        localized = timestamps\n",
    "    \n",
    "    # 转换\n",
    "    converted = localized.dt.tz_convert(to_tz)\n",
    "    return converted\n",
    "\n",
    "# 示例使用\n",
    "sample_times = [\n",
    "    '2023-06-15 09:00:00',\n",
    "    '2023-06-15 12:00:00', \n",
    "    '2023-06-15 18:00:00',\n",
    "    '2023-06-15 21:00:00'\n",
    "]\n",
    "\n",
    "print(\"批量时区转换示例:\")\n",
    "print(\"原始时间（假设为上海时间）:\")\n",
    "for time in sample_times:\n",
    "    print(f\"  {time}\")\n",
    "\n",
    "converted_times = convert_timezone_batch(sample_times, 'Asia/Shanghai', 'US/Eastern')\n",
    "print(\"\\n转换为纽约时间:\")\n",
    "for orig, conv in zip(sample_times, converted_times):\n",
    "    print(f\"  {orig} -> {conv}\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.8.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
